package com.cdn.openapi.aop;

import cn.hutool.core.bean.BeanUtil;
import com.cdn.openapi.anno.AuthCheck;
import com.cdn.openapi.consts.SignConst;
import com.cdn.openapi.exeception.AuthException;
import com.cdn.openapi.utils.AppUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 商户账户校验
 *
 * @author 蔡定努
 * @date 2023/08/25 14:54
 */
@Slf4j
@Component
@Aspect
@Order(Integer.MAX_VALUE - 1)
public class MerchantCheckAspect {

    @Pointcut("@annotation(com.cdn.openapi.anno.AuthCheck)")
    public void pointcut() {
    }

    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint) {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        Object[] args = joinPoint.getArgs();
        assert ra != null;
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) ra;
        HttpServletRequest request = requestAttributes.getRequest();
        Map<String, Object> headerMap = getStringObjectMap(request);
        Object param = args.length==0?null:args[0];
        Map<String, Object> bodyMap = BeanUtil.beanToMap(param);

        // 签名验证
        AppUtil.serverVerify(headerMap, bodyMap==null?new HashMap<>():bodyMap);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        AuthCheck merchantCheck = signature.getMethod().getAnnotation(AuthCheck.class);
        String value = merchantCheck.value();
        String appId = headerMap.get(SignConst.APP_ID).toString();
        log.info("appId:{},准备调用{},code:{}", appId,request.getRequestURI(), value);
        // 权限验证
        boolean hasAuth = AppUtil.hasAuth(appId, value);
        if (!hasAuth) {
            throw new AuthException("接口未开通，请联系管理员");
        }
    }

    private static Map<String, Object> getStringObjectMap(HttpServletRequest request) {

        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put(SignConst.APP_ID, request.getHeader(SignConst.APP_ID));
        headerMap.put(SignConst.NONCE, request.getHeader(SignConst.NONCE));
        headerMap.put(SignConst.SIGN, request.getHeader(SignConst.SIGN));
        headerMap.put(SignConst.TIMESTAMP, request.getHeader(SignConst.TIMESTAMP));
        return headerMap;
    }


}
